using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using BussinessLogicTecnoPez;
using System.Reflection;
using System.Web.UI;
using System.Data;

namespace Tecnopez.Globals
{
    /// <summary>
    /// Clase que automatiza la configuracion e inicializacion de grillas.
    /// </summary>
    public class GrdViewInitializator<T> where T : new()
    {

        private bool allowSort;
        private StateBag ViewState;
        private String viewStateOrdenKey;
        private String viewStateOrdenDireccionKey;
        public delegate void cargarGrillaHandler();
        private cargarGrillaHandler CargarGrilla;
        private GridView grdInitialized;

        //La idea es que si el cargar grilla esta vacia que muestre los encabezados
        private DataTable objEmptyGrid;

        /// <summary>
        /// Constructor para inicializar grillas. Luego de instancearlo
        /// es necesario llamar al metodo gridViewSetup para configurar la
        /// grilla. El constructor no configura la grilla.
        /// </summary>
        /// <param name="entityClass">Clase de entidad que tiene atributos fryendly name y de gestion generica a acoplar a la tabla </param>
        /// <param name="AllowSort">Si se va a o no a permitir el ordenamiento de la grilla.</param>
        public GrdViewInitializator(StateBag pageViewState, String pageViewStateOrdenKey, String pageViewStateOrdenDireccionKey, bool AllowSort, cargarGrillaHandler cargarGrilla)
        {
            CargarGrilla = cargarGrilla;
            allowSort = AllowSort;
            ViewState = pageViewState;
            viewStateOrdenKey = pageViewStateOrdenKey;
            viewStateOrdenDireccionKey = pageViewStateOrdenDireccionKey;
        }
        /// <summary>
        /// Funcion que configura la grilla.
        /// </summary>
        /// <param name="gridToInitalize">Grilla a inicializar</param>
        /// <param name="withCompactView">Si desea o no ver la grilla compacta</param>

        public void gridViewSetup(GridView gridToInitalize, bool withCompactView, DataControlField[] botones)
        {
            grdInitialized = gridToInitalize;
            Type classType;
            classType = typeof(T);
            List<string> keys = new List<string>();
            gridToInitalize.EnableViewState = false;
            gridToInitalize.AutoGenerateColumns = false;
            gridToInitalize.AllowPaging = true;
            gridToInitalize.PageSize = Convert.ToInt32(Functions.getConfiguration("cantPaginasPorDefecto"));
            gridToInitalize.PagerSettings.Mode = PagerButtons.NextPrevious;
            gridToInitalize.PagerSettings.NextPageText = Functions.getConfiguration("textoBotonSiguiente");
            gridToInitalize.PagerSettings.PreviousPageText = Functions.getConfiguration("textoBotonAnterior");
            gridToInitalize.AllowSorting = allowSort;
            PropertyInfo[] PI = classType.GetProperties();
            foreach (PropertyInfo p in PI)
            {
                Object[] colObj = p.GetCustomAttributes(false);
                foreach (Object obj in colObj)
                {
                    verificarSiEsClave(keys, p, obj);
                    FriendlyName DBf = obj as FriendlyName;
                    if (DBf != null)
                    {
                       

                        if (withCompactView)
                        {
                            if (!DBf.ShowInCompactPresentation)
                            {
                                continue;
                            }
                        }
                        configurarColumna(gridToInitalize, p, DBf);
                    } 
                    
                    //Generar todas las columnas que sean necesarias para el datable falso.
                    if (objEmptyGrid == null)
                    {
                        objEmptyGrid = new DataTable();
                    }
                    if (objEmptyGrid.Columns[p.Name] == null)
                    {
                        objEmptyGrid.Columns.Add(p.Name);
                    }
                }
            }
            gridToInitalize.DataKeyNames = keys.ToArray();
            int columnasExtras = gridToInitalize.Columns.Count;
            for (int i = 0; i < botones.Length; i++)
            {
                gridToInitalize.Columns.Add(botones[i]);
            }
            gridToInitalize.PageIndexChanging+=new GridViewPageEventHandler(gridToInitalize_PageIndexChanging);
            if (allowSort)
            {
                gridToInitalize.Sorting += new GridViewSortEventHandler(gridToInitalize_Sorting);
            }
            if (CargarGrilla != null)
            {
                CargarGrilla();
            }
            if (gridToInitalize.Rows.Count == 0)
            {
                foreach (string strKeys in grdInitialized.DataKeyNames)
                {
                    if (objEmptyGrid.Columns[strKeys] == null)
                    {
                        objEmptyGrid.Columns.Add(strKeys, typeof(long));
                    }
                }
                objEmptyGrid.Rows.Add(objEmptyGrid.NewRow());
                gridToInitalize.DataSource = objEmptyGrid;
                gridToInitalize.DataBind();
                gridToInitalize.ShowHeader = true;
                //for (; columnasExtras < gridToInitalize.Columns.Count; columnasExtras++)
                //{
                //    gridToInitalize.Columns[columnasExtras].Visible = false;
                //}
            }
        }

        private void gridToInitalize_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            this.grdInitialized.PageIndex = e.NewPageIndex;
            if (CargarGrilla != null)
            {
                CargarGrilla();
            }
        }

        private bool permisoParaOrdenar(string columna)
        {
            bool result = true;
            Type tipoDeLaGrilla = typeof(T);
            //   EntityBase<Type>.getManager.isValidField
            Object auxObj = Activator.CreateInstance(tipoDeLaGrilla);
            MethodInfo[] metodos;
            metodos = tipoDeLaGrilla.BaseType.GetMethods();
            foreach (MethodInfo m in metodos)
            {
                if (m.Name == "get_getManager")
                {
                    Type genericType;
                    genericType = m.Invoke(auxObj, null).GetType();
                    Object auxObjGen = Activator.CreateInstance(genericType);
                    MethodInfo[] metodosGenericos;
                    metodosGenericos = genericType.GetMethods();
                    foreach (MethodInfo gm in metodosGenericos)
                    {
                        if (gm.Name == "isValidField")
                        {
                            object[] parametro = new object[1];
                            parametro[0] = columna;
                            return Convert.ToBoolean(gm.Invoke(auxObjGen, parametro));
                        }
                    }
                }
            }

            return result;
        }

        private void gridToInitalize_Sorting(object sender, GridViewSortEventArgs e)
        {
            if (!permisoParaOrdenar(e.SortExpression))
            {
                Functions.MessageBox("No se puede ordenar por esa columna", grdInitialized.Page);
                return;
            }

            GenericManager<T>.Order.orderDirection direccion;
            if (ViewState[viewStateOrdenDireccionKey] != null)
            {
                direccion = (GenericManager<T>.Order.orderDirection)ViewState[viewStateOrdenDireccionKey];
                if (direccion == GenericManager<T>.Order.orderDirection.ASC && ViewState[viewStateOrdenKey].ToString() == e.SortExpression)
                {
                    direccion = GenericManager<T>.Order.orderDirection.DESC;
                }
                else
                {
                    direccion = GenericManager<T>.Order.orderDirection.ASC;
                }
            }
            else
            {
                direccion = GenericManager<T>.Order.orderDirection.ASC;
            }
            ViewState.Add(viewStateOrdenKey, e.SortExpression);
            ViewState.Add(viewStateOrdenDireccionKey, direccion);
            if (CargarGrilla != null)
            {
                CargarGrilla();
            }
        }

        private void configurarColumna(GridView gridToInitalize, PropertyInfo p, FriendlyName DBf)
        {
            

            BoundField col = new BoundField();
            col.DataField = p.Name;
            col.HeaderText = DBf.myFriendlyName;
            col.SortExpression = p.Name;
            if (p.PropertyType == typeof(Int16) ||
                p.PropertyType == typeof(Int32))
            {
                col.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
            }
            else if (p.PropertyType == typeof(Int16))
            {
                col.ItemStyle.HorizontalAlign = HorizontalAlign.Center;
            }
            gridToInitalize.Columns.Add(col);
        }

        private void verificarSiEsClave(List<string> keys, PropertyInfo p, Object obj)
        {
            DBField dfi = obj as DBField;
            if (dfi != null)
            {
                if (dfi.IsKey && dfi.IsForeingKey==false)
                {
                    keys.Add(p.Name);
                }
            }
        }
    }

//-------------------Prueba David-----------------------------
    public class GrdViewInitializator
    {

        private bool allowSort;
        private StateBag ViewState;
        private String viewStateOrdenKey;
        private String viewStateOrdenDireccionKey;
        public delegate void cargarGrillaHandler();
        private cargarGrillaHandler CargarGrilla;
        private GridView grdInitialized;
        private Type classType;


        /// <summary>
        /// Constructor para inicializar grillas. Luego de instancearlo
        /// es necesario llamar al metodo gridViewSetup para configurar la
        /// grilla. El constructor no configura la grilla.
        /// </summary>
        /// <param name="entityClass">Clase de entidad que tiene atributos fryendly name y de gestion generica a acoplar a la tabla </param>
        /// <param name="AllowSort">Si se va a o no a permitir el ordenamiento de la grilla.</param>
        public GrdViewInitializator(StateBag pageViewState, String pageViewStateOrdenKey, String pageViewStateOrdenDireccionKey, bool AllowSort, cargarGrillaHandler cargarGrilla, Type pclassType)
        {
            classType = pclassType;
            CargarGrilla = cargarGrilla;
            allowSort = AllowSort;
            ViewState = pageViewState;
            viewStateOrdenKey = pageViewStateOrdenKey;
            viewStateOrdenDireccionKey = pageViewStateOrdenDireccionKey;
        }
        /// <summary>
        /// Funcion que configura la grilla.
        /// </summary>
        /// <param name="gridToInitalize">Grilla a inicializar</param>
        /// <param name="withCompactView">Si desea o no ver la grilla compacta</param>

        public void gridViewSetup(GridView gridToInitalize, bool withCompactView, DataControlField[] botones)
        {
            grdInitialized = gridToInitalize;
            //Type classType;
            //classType = typeof(T);
            List<string> keys = new List<string>();
            gridToInitalize.EnableViewState = false;
            gridToInitalize.AutoGenerateColumns = false;
            gridToInitalize.AllowPaging = true;
            gridToInitalize.PageSize = Convert.ToInt32(Functions.getConfiguration("cantPaginasPorDefecto"));
            gridToInitalize.PagerSettings.Mode = PagerButtons.NextPrevious;
            gridToInitalize.PagerSettings.NextPageText = Functions.getConfiguration("textoBotonSiguiente");
            gridToInitalize.PagerSettings.PreviousPageText = Functions.getConfiguration("textoBotonAnterior");
            gridToInitalize.AllowSorting = allowSort;
            PropertyInfo[] PI = classType.GetProperties();
            foreach (PropertyInfo p in PI)
            {
                Object[] colObj = p.GetCustomAttributes(false);
                foreach (Object obj in colObj)
                {
                    verificarSiEsClave(keys, p, obj);
                    FriendlyName DBf = obj as FriendlyName;
                    if (DBf != null)
                    {
                        if (withCompactView)
                        {
                            if (!DBf.ShowInCompactPresentation)
                            {
                                continue;
                            }
                        }
                        configurarColumna(gridToInitalize, p, DBf);
                    }
                }
            }
            gridToInitalize.DataKeyNames = keys.ToArray();
            for (int i = 0; i < botones.Length; i++)
            {
                gridToInitalize.Columns.Add(botones[i]);
            }
            gridToInitalize.PageIndexChanging += new GridViewPageEventHandler(gridToInitalize_PageIndexChanging);
            if (allowSort)
            {
                gridToInitalize.Sorting += new GridViewSortEventHandler(gridToInitalize_Sorting);
            }
            if (CargarGrilla != null)
            {
                CargarGrilla();
            }
        }

        private void gridToInitalize_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {
            this.grdInitialized.PageIndex = e.NewPageIndex;
            if (CargarGrilla != null)
            {
                CargarGrilla();
            }
        }

        private void gridToInitalize_Sorting(object sender, GridViewSortEventArgs e)
        {
            GenericManager<auxClass>.Order.orderDirection direccion;
            if (ViewState[viewStateOrdenDireccionKey] != null)
            {
                direccion = (GenericManager<auxClass>.Order.orderDirection)ViewState[viewStateOrdenDireccionKey];
                if (direccion == GenericManager<auxClass>.Order.orderDirection.ASC && ViewState[viewStateOrdenKey].ToString() == e.SortExpression)
                {
                    direccion = GenericManager<auxClass>.Order.orderDirection.DESC;
                }
                else
                {
                    direccion = GenericManager<auxClass>.Order.orderDirection.ASC;
                }
            }
            else
            {
                direccion = GenericManager<auxClass>.Order.orderDirection.ASC;
            }
            ViewState.Add(viewStateOrdenKey, e.SortExpression);
            ViewState.Add(viewStateOrdenDireccionKey, direccion);
            if (CargarGrilla != null)
            {
                CargarGrilla();
            }
        }

        private void configurarColumna(GridView gridToInitalize, PropertyInfo p, FriendlyName DBf)
        {
            BoundField col = new BoundField();
            col.DataField = p.Name;
            col.HeaderText = DBf.myFriendlyName;
            col.SortExpression = p.Name;
            if (p.PropertyType == typeof(Int16) ||
                p.PropertyType == typeof(Int32))
            {
                col.ItemStyle.HorizontalAlign = HorizontalAlign.Right;
            }
            else if (p.PropertyType == typeof(Int16))
            {
                col.ItemStyle.HorizontalAlign = HorizontalAlign.Center;
            }
            gridToInitalize.Columns.Add(col);
        }

        private void verificarSiEsClave(List<string> keys, PropertyInfo p, Object obj)
        {
            DBField dfi = obj as DBField;
            if (dfi != null)
            {
                if (dfi.IsKey && dfi.IsForeingKey == false)
                {
                    keys.Add(p.Name);
                }
            }
        }
        private class auxClass { };
    }

}
